package esri.mrm.mobile.activity;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.XML;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.AssetManager;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Parcelable;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ListView;
import android.widget.Toast;
import com.esri.android.map.ags.ArcGISFeatureLayer;
import com.esri.core.map.CallbackListener;
import com.esri.core.map.FeatureSet;
import com.esri.core.map.Field;
import com.esri.core.map.Graphic;
import com.esri.core.tasks.ags.query.Query;
import esri.mrm.mobile.AGSObjects;
import esri.mrm.mobile.LayerUtility;
import esri.mrm.mobile.NonServiceWorkOrderType;
import esri.mrm.mobile.R;
import esri.mrm.mobile.StopsConfigurations;
import esri.mrm.mobile.WorkOrder;
import esri.mrm.mobile.WorkOrderStatus;
import esri.mrm.mobile.WorkOrderUtility;
import esri.mrm.mobile.adapter.WorkOrderAdapter;
import esri.mrm.mobile.adapter.WorkOrderSpinnerAdapter;
import esri.mrm.mobile.task.CompleteListener;
import esri.mrm.mobile.task.SaveStopTask;
public class WorkOrdersActivity extends Activity implements CompleteListener
{
StopsConfigurations configs;
Graphic route;
final List<WorkOrder> workOrders = new ArrayList<WorkOrder>();
private Toast toast;
private long lastBackPressTime = 0;
private Context context;
private ListView list;
private AGSObjects agsObjects;
private ArcGISFeatureLayer stopLayer;
private String whereClause;
private ScheduledExecutorService scheduledTaskExecutor;
private boolean refreshStops;
private int reloadInterval;
private SharedPreferences sharedPrefs;
private ProgressDialog progressDialog;
private AlertDialog resequenceDialog;
public static final String TAG = "WorkOrdersActivity";
public static final String stopConfigFileName = "stops-configurations.xml";
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// setContentView(R.layout.workorder_list);
View viewToLoad = LayoutInflater.from(this.getParent()).inflate(R.layout.workorder_list, null);
this.setContentView(viewToLoad);
setContext(viewToLoad.getContext());
list = (ListView) findViewById(R.id.workorders);
list.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> av, View v, int position, long id)
{
WorkOrderAdapter workorderAdapter = (WorkOrderAdapter) av.getAdapter();
ShowItemClick(workorderAdapter, v, position);
}
});
readStopConfigurations();
agsObjects = ((AGSObjects) getApplicationContext());
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
list.setOnItemLongClickListener(new OnItemLongClickListener()
{
public boolean onItemLongClick(AdapterView<?> av, View v, int position, long id)
{
WorkOrderAdapter workorderAdapter = (WorkOrderAdapter) av.getAdapter();
final WorkOrder longPressedWorkOrder = workorderAdapter.getItem(position);
final WorkOrder previousWorkOrder = getPreviousWorkOrder(longPressedWorkOrder);
if(longPressedWorkOrder.getStatus().equals(WorkOrderStatus.AtStop.toString()) || longPressedWorkOrder.getStatus().equals(WorkOrderStatus.Completed.toString()) || longPressedWorkOrder.getStatus().equals(WorkOrderStatus.Exception.toString()) )
{
showAlertMessage("Warning", "Cannot move a stop with the status " + longPressedWorkOrder.getStatus());
return true;
}
if(longPressedWorkOrder.getType().equals(NonServiceWorkOrderType.Base.toString()))
{
showAlertMessage("Warning", "Cannot move a base stop. ");
return true;
}
refreshStops = false;
List<WorkOrder> newList = new ArrayList<WorkOrder>();
if( longPressedWorkOrder.getType().equals(NonServiceWorkOrderType.Break.toString()) || longPressedWorkOrder.getType().equals(NonServiceWorkOrderType.Lunch.toString()) )
newList = WorkOrderUtility.getWorkOrderListForBreaks(workOrders);
else
newList = WorkOrderUtility.getWorkOrderListForWorkOrder(workOrders, longPressedWorkOrder);
final WorkOrderSpinnerAdapter adapterWorkOrders = new WorkOrderSpinnerAdapter(WorkOrdersActivity.this, newList);
ListView listView = new ListView(getContext());
listView.setAdapter(adapterWorkOrders);
listView.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> listView, View itemView, int position, long itemId)
{
try
{
final WorkOrder woBefore = adapterWorkOrders.getItem(position);
//showAlertMessage("Test", "selected wo " + woBefore.getStopName());
if(woBefore.getStopName().equals(previousWorkOrder.getStopName()))
{
showAlertMessage("Info", "The work order is inserted into the same position. No route update is needed.");
}
else
{
new AlertDialog.Builder(getContext())
.setTitle("Please Confirm")
.setMessage("Are you sure you want to move work order " + longPressedWorkOrder.getStopName() + " after " + woBefore.getStopName() + "?")
.setIcon(android.R.drawable.ic_dialog_alert)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
if(longPressedWorkOrder.getSequence()<woBefore.getSequence())
longPressedWorkOrder.setSequence(woBefore.getSequence());
else
longPressedWorkOrder.setSequence(woBefore.getSequence()+1);
if(resequenceDialog != null)
resequenceDialog.dismiss();
String url = sharedPrefs.getString("gep_url_port", "") + sharedPrefs.getString("gep_update_stop_path", "");
new SaveStopTask(longPressedWorkOrder, WorkOrdersActivity.this, getContext(), WorkOrdersActivity.this).execute(url);
}})
.setNegativeButton(android.R.string.no, null).show();
}
}
catch (Exception e)
{
Log.d(TAG, e.getMessage());
refreshStops = true;
}
}
});
listView.setBackgroundColor(Color.WHITE);
resequenceDialog = new AlertDialog.Builder(getContext()).setTitle("Move work order after:").setNegativeButton("Cancel", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int i)
{
refreshStops = true;
dialog.dismiss();
}
}).setView(listView).create();
resequenceDialog.show();
return true;
}
});
}
private WorkOrder getPreviousWorkOrder(WorkOrder thisWorkOrder)
{
int seq = thisWorkOrder.getSequence();
for (WorkOrder wo : workOrders)
{
if(wo.getSequence()==seq-1)
return wo;
}
return null;
}
private void readStopConfigurations()
{
try
{
File downloadFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File stopConfigDownload = new File(downloadFolder.getAbsolutePath() + File.separator + stopConfigFileName);
if(stopConfigDownload.exists())
{
System.out.println(">>>>>>>>>> Stop Configuration Download Exists. <<<<<<<<<<<<<<<<");
copyStopConfigFromDownload(stopConfigDownload);
}
else
{
System.out.println(">>>>>>>>>> Stop Configuration Download Does NOT Exist. <<<<<<<<<<<<<<<<");
try
{
InputStream inputStream = openFileInput(stopConfigFileName);
if(inputStream != null)
{
inputStream.close();
System.out.println(">>>>>>>>>> Stop Configuration Local File Exists. <<<<<<<<<<<<<<<<");
}
}
catch(FileNotFoundException e)
{
System.out.println(">>>>>>>>>> Stop Configuration Local File Does NOT Exist. <<<<<<<<<<<<<<<<");
copyStopConfigFromAsset();
}
}
System.out.println(">>>>>>>>>> Reading Stop Configuration Local File. <<<<<<<<<<<<<<<<");
readStopConfigFromLocal();
}
catch(Exception e)
{
Log.e("WorkOrder activity", "Can not read stop configuration: " + e.getMessage());
showAlertMessage("Error", "Cannot read stop configuration.");
}
}
private void copyStopConfigFromDownload(File stopConfigDownload)
{
FileInputStream fin;
try
{
fin = new FileInputStream(stopConfigDownload);
BufferedReader reader = new BufferedReader(new InputStreamReader(fin));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
reader.close();
fin.close();
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(openFileOutput(stopConfigFileName, Context.MODE_PRIVATE));
outputStreamWriter.write(sb.toString());
outputStreamWriter.close();
}
catch (FileNotFoundException e)
{
Log.e("WorkOrder activity", "File not found: " + e.toString());
}
catch (IOException e)
{
Log.e("WorkOrder activity", "Can not read or write file: " + e.toString());
}
}
private void copyStopConfigFromAsset()
{
try
{
AssetManager am = context.getAssets();
InputStream is = am.open("stops-configurations.xml");
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int i;
i = is.read();
while (i != -1)
{
byteArrayOutputStream.write(i);
i = is.read();
}
is.close();
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(openFileOutput(stopConfigFileName, Context.MODE_PRIVATE));
outputStreamWriter.write(byteArrayOutputStream.toString());
outputStreamWriter.close();
}
catch (IOException e)
{
Log.e("WorkOrder activity", "Can not read or write file: " + e.toString());
}
}
private void readStopConfigFromLocal()
{
try
{
InputStream inputStream = openFileInput(stopConfigFileName);
if (inputStream != null)
{
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String receiveString = "";
StringBuilder stringBuilder = new StringBuilder();
while ((receiveString = bufferedReader.readLine()) != null)
{
stringBuilder.append(receiveString);
}
inputStream.close();
JSONObject xmlJSONObj = XML.toJSONObject(stringBuilder.toString());
configs = new StopsConfigurations(xmlJSONObj);
}
}
catch(IOException e)
{
Log.e("WorkOrder activity", "Can not read file: " + e.toString());
}
catch (JSONException e)
{
Log.e("WorkOrder activity", "Can not parse XML to JSON: " + e.toString());
}
}
@Override
public void onBackPressed()
{
if (this.lastBackPressTime < System.currentTimeMillis() - 4000)
{
toast = Toast.makeText(this, "Press Back button agian to close the app", Toast.LENGTH_LONG);
toast.show();
this.lastBackPressTime = System.currentTimeMillis();
}
else
{
if (toast != null)
{
toast.cancel();
}
super.onBackPressed();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.mrm_stopmenu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
// Handle item selection
switch (item.getItemId())
{
case R.id.addbreak:
addBreak();
return true;
default:
return true;
// return super.onOptionsItemSelected(item);
}
}
private void addBreak()
{
if(WorkOrderUtility.getWorkOrderListForBreaks(workOrders).size()==0)
{
new AlertDialog.Builder(this).setTitle("Warning").setMessage("Cannot add new break due to the lack of stops.").setPositiveButton("OK", null).show();
}
else
{
Class<?> cls = StopTypeActivity.class;
String activity = "";
activity = "StopTypeActivity";
cls = StopTypeActivity.class;
// Toast.makeText(this, message.getName(), Toast.LENGTH_SHORT).show();
Intent intent = new Intent(getParent(), cls);
Bundle b = new Bundle();
b.putParcelableArray("WorkOrders", workOrders.toArray(new Parcelable[workOrders.size()]));
b.putParcelable("stopsConfigurations", configs);
intent.putExtras(b);
TabGroupActivity parentActivity = (TabGroupActivity) getParent();
parentActivity.startChildActivity(activity, intent);
}
}
private void ShowItemClick(WorkOrderAdapter workorderAdapter, View v, int position)
{
WorkOrder workorder = workorderAdapter.getItem(position);
Class<?> cls = WorkOrderDetailActivity.class;
String activity = "";
activity = "WorkOrderDetailActivity";
cls = WorkOrderDetailActivity.class;
// Toast.makeText(this, message.getName(), Toast.LENGTH_SHORT).show();
Intent intent = new Intent(getParent(), cls);
Bundle b = new Bundle();
b.putParcelable("WorkOrder", workorder);
b.putParcelableArray("WorkOrders", workOrders.toArray(new Parcelable[workOrders.size()]));
b.putParcelable("stopsConfigurations", configs);
intent.putExtras(b);
TabGroupActivity parentActivity = (TabGroupActivity) getParent();
parentActivity.startChildActivity(activity, intent);
}
public void SetWorkOrdersAdapter(List<WorkOrder> workOrders)
{
// ListView list = (ListView) findViewById(R.id.workorders);
WorkOrderAdapter adapter = (WorkOrderAdapter) list.getAdapter();
if (adapter == null)
{
adapter = new WorkOrderAdapter(this, workOrders, configs);
list.setAdapter(adapter);
}
adapter.sort(new Comparator<WorkOrder>()
{
public int compare(WorkOrder lhs, WorkOrder rhs)
{
return lhs.getSequence() - rhs.getSequence();
}
});
adapter.notifyDataSetChanged();
// list.requestLayout();
}
private void showProgressDialog()
{
if (progressDialog != null)
{
progressDialog.dismiss();
progressDialog = null;
}
progressDialog = new ProgressDialog(context);
progressDialog.setTitle("Reloading Stops");
progressDialog.setMessage("Please wait...");
progressDialog.setCancelable(false);
progressDialog.setIndeterminate(true);
progressDialog.show();
timerDelayRemoveDialog(10000, progressDialog);
}
private void loadPreferences()
{
reloadInterval = Integer.parseInt(sharedPrefs.getString("wo_update_interval", "10000"));
}
private void scheduleLoadStops()
{
refreshStops = true;
// workOrders.clear();
if (scheduledTaskExecutor != null)
{
scheduledTaskExecutor.shutdown();
scheduledTaskExecutor = null;
}
scheduledTaskExecutor = Executors.newScheduledThreadPool(1);
scheduledTaskExecutor.scheduleAtFixedRate(new Runnable()
{
public void run()
{
if (refreshStops)
loadStops();
}
}, 0, reloadInterval / 1000, TimeUnit.SECONDS);
}
private void loadStops()
{
if (agsObjects.getStopsLayer() == null)
{
WorkOrdersActivity.this.runOnUiThread(new Runnable()
{
public void run()
{
SetWorkOrdersAdapter(workOrders);
}
});
return;
}
stopLayer = agsObjects.getStopsLayer();
WorkOrdersActivity.this.runOnUiThread(new Runnable()
{
public void run()
{
showProgressDialog();
}
});
String routeFieldName = LayerUtility.getFieldNamebyAlias(stopLayer, getResources().getString(R.string.ALIAS_STOPSLAYER_ROUTE_NAME));
whereClause = routeFieldName + "='" + agsObjects.getRouteId() + "'";
Query query = new Query();
query.setWhere(whereClause);
query.setOutFields(new String[] { "*" });
try
{
stopLayer.queryFeatures(query, new CallbackListener<FeatureSet>()
{
public void onCallback(FeatureSet queryResults)
{
workOrders.clear();
if (queryResults.getGraphics().length > 0)
{
Map<String, Integer> fieldTypes = new HashMap<String, Integer>();
Map<String, String> fieldAliases = new HashMap<String, String>();
for (Field field : queryResults.getFields())
{
fieldTypes.put(field.getAlias(), field.getFieldType());
fieldAliases.put(field.getName(), field.getAlias());
}
for (int i = 0; i < queryResults.getGraphics().length; i++)
{
Graphic graphic = queryResults.getGraphics()[i];
WorkOrder workOrder = new WorkOrder(graphic, fieldTypes, fieldAliases, context);
workOrders.add(workOrder);
}
}
WorkOrdersActivity.this.runOnUiThread(new Runnable()
{
public void run()
{
SetWorkOrdersAdapter(workOrders);
}
});
progressDialog.dismiss();
}
public void onError(Throwable e)
{
Log.d(TAG, "Select Features Error" + e.getLocalizedMessage());
progressDialog.dismiss();
}
});
}
catch (Exception e)
{
progressDialog.dismiss();
}
}
protected Context getContext()
{
return context;
}
protected void setContext(Context context)
{
this.context = context;
}
@Override
protected void onDestroy()
{
super.onDestroy();
if (scheduledTaskExecutor != null)
{
scheduledTaskExecutor.shutdownNow();
scheduledTaskExecutor = null;
}
}
@Override
protected void onPause()
{
super.onPause();
refreshStops = false;
}
@Override
protected void onResume()
{
super.onResume();
loadPreferences();
scheduleLoadStops();
refreshStops = true;
}
@Override
protected void onStop()
{
super.onStop();
}
@Override
protected void onStart()
{
super.onStart();
}
public void timerDelayRemoveDialog(long time, final Dialog d){
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
if(d != null)
d.dismiss();
}
}, time);
}
private void showAlertMessage(final String title, final String body)
{
WorkOrdersActivity.this.runOnUiThread(new Runnable()
{
public void run()
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext());
// set title
alertDialogBuilder.setTitle(title);
// set dialog message
alertDialogBuilder.setMessage(body).setCancelable(false).setPositiveButton(R.string.okButtonLabel, new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
dialog.cancel();
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
});
}
public void resultCallback(boolean result)
{
refreshStops = true;
}
}